package eerbaar.shared.persist.internal.lib;

import java.util.ArrayList;
import java.util.List;

import eerbaar.body.BodyConstants;
import eerbaar.body.IHead;
import eerbaar.elements.ElementConstants;
import eerbaar.elements.extension.IPoints;
import eerbaar.persona.IPersona;
import eerbaar.persona.PersonaConstants;
import eerbaar.persona.PersonaFactory;
import eerbaar.position.IPosition;
import eerbaar.position.PositionConstants;
import eerbaar.shared.exceptions.GameRuntimeException;
import eerbaar.shared.persist.IPersistService;
import eerbaar.shared.persist.IPersister;
import eerbaar.shared.persist.ISaver;
import eerbaar.shared.service.ServiceFactory;
import eerbaar.shared.tree.IAttributes;
import eerbaar.shared.tree.INode;
import eerbaar.shared.tree.NodeCmdFactory;

public class PersonaPersister implements IPersister<IPersona> {

    private IPersona target;

    public PersonaPersister() {
        //
    }

    public PersonaPersister(INode node) throws GameRuntimeException {
        load(node);
    }

    @Override
    public Class<IPersona> getRegistertedInterface() {
        return IPersona.class;
    }

    @Override
    public ISaver<?>[] getSavableChildren() {

        List<ISaver<?>> result = new ArrayList<ISaver<?>>();

        ISaver<?> savable;
        savable = new PositionPersister(this.target.getPosition());
        result.add(savable);
        savable = new HeadPersister(this.target.getHead());
        result.add(savable);

        return result.toArray(new ISaver[] {});
    }

    @Override
    public String getSavableName() {
        return PersonaConstants.PERSONA;
    }

    @Override
    public IPersona getTarget() {
        return this.target;
    }

    @Override
    public boolean isAssignableFrom(ISaver<?> persist) {

        if (persist instanceof ElementPersister) {

            Object obj = persist.getTarget();
            if (obj instanceof IPersona) {

                return true;
            }
        }

        return false;
    }

    @Override
    public IPersona load(INode node) {
        assert (node != null);

        IAttributes a = node.getAttributes();

        IPersistService service = ServiceFactory
                .getService(IPersistService.class);
        IPersister<IHead> p = service.getPersister(IHead.class);

        INode headNode = NodeCmdFactory.findChild(node, BodyConstants.HEAD);
        IHead head = p.load(headNode);

        INode positionNode = NodeCmdFactory.findChild(node,
                PositionConstants.NAME);

        int points = 0;
        IPosition position = new PositionPersister().load(positionNode);
        if (a.get(Integer.class, ElementConstants.POINTS) != null) {
            points = a.get(Integer.class, ElementConstants.POINTS);
        }

        String elementType = a.get(String.class, ElementConstants.NAME);

        String program = null;
        if (a.get(String.class, "program") != null) {
            program = a.get(String.class, "program");
        }

        return PersonaFactory.create(elementType, position, head, points,
                program);
    }

    @Override
    public void saveAttributes(INode node) {

        IAttributes a = node.getAttributes();

        a.set(String.class, ElementConstants.TYPE,
                ElementConstants.ELEMENT_NAME);
        a.set(String.class, ElementConstants.NAME, this.target.getName());

        IPoints points = this.target.getExtension(IPoints.class);
        if (points != null) {
            a.set(Integer.class, ElementConstants.POINTS, points.getPoints());
        }
        if (this.target.getProgram() != null) {
            a.set(String.class, "program", this.target.getProgram());
        }
    }

    @Override
    public void setTarget(IPersona obj) {
        this.target = obj;
    }

}
